#pragma once
#include <stdlib.h>
#include <string>
#include <sstream>
#include "common.h"
using namespace std;

//Definitions
#if 1
//_HEADER
typedef enum FRAME_FIX
{
	HEADER_TAIL_LENGTH	= 2,
	HEADER_HEAD_LENGTH	= 6, //H+L+L+H	 = 1+2+2+1=6
	HEADER_COMM_LENGTH	= 8, //C+A+F+S	 = 1+5+1+1=8
	HEADER_DATA_MINLEN	= 12,//COMM+PNFN = 8+4=12
	HEADER_DATA_INDEX	= 14,//HEAD+COMM = 6+8=14
	HEADER_FIX_ENDING	= 0x16,
	HEADER_FIX_BEGIN    = 0x68}FRAME_FIX;

//_CONTROL
typedef enum CONTROL_FUN_PASIVE
{
	CONTROL_FUN_PASIVE_00_ACK  = 0x00,
	CONTROL_FUN_PASIVE_08_DATA = 0x08,
	CONTROL_FUN_PASIVE_09_NODA = 0x09,
	CONTROL_FUN_PASIVE_0B_LINK = 0x0B}CONTROL_FUN_PASIVE;

typedef enum CONTROL_FUN_ACTIVE
{
	CONTROL_FUN_ACTIVE_09_LINK = 0x09,
	CONTROL_FUN_ACTIVE_0A_ASK1 = 0x0A,
	CONTROL_FUN_ACTIVE_0B_ASK2 = 0x0B}CONTROL_FUN_ACTIVE;

typedef enum CONTROL_PRM
{
	CONTROL_PRM_PAS = 0,
	CONTROL_PRM_ACT = 1}CONTROL_PRM;

typedef enum CONTROL_DIR
{
	CONTROL_DIR_M2S = 0, 
	CONTROL_DIR_S2M = 1}CONTROL_DIR;

//_SEQUENCE
typedef enum SEQUENCE_TPV
{
	SEQUENCE_TPV_NO  = 0,
	SEQUENCE_TPV_YES = 1}SEQUENCE_TPV; 

typedef enum SEQUENCE_POS
{
	SEQUENCE_POS_MID= 0,
	SEQUENCE_POS_FIN= 1,
	SEQUENCE_POS_FIR= 2,
	SEQUENCE_POS_ONE= 3}SEQUENCE_POS;

typedef enum SEQUENCE_CON
{
	SEQUENCE_CON_NO  = 0,
	SEQUENCE_CON_YES = 1}SEQUENCE_CON; 


//_FUNCTION_NUMBER
typedef enum FUNCTION_NUMBER
{
	FUNCTION_00_CONFIRM   = 0x00,
	FUNCTION_02_HEARTBEAT = 0x02,
	FUNCTION_04_SETTASK   = 0x04,
	FUNCTION_0D_HISTORY   = 0x0D}FUNCTION_NUMBER;

#endif//ENUMS

#pragma pack(1)
class Header
{
public:
	uint8_t  H1:8;
	uint16_t V1:2;
	uint16_t L1:14;
	uint16_t V2:2;
	uint16_t L2:14;
	uint8_t  H2:8;
public:
	void initDataMinLen(uint16_t l=HEADER_DATA_MINLEN);
	bool check(void)const;
	bool append(class Buffer& b);
};
class Control
{
public:
	uint8_t  FUN:4;
	uint8_t  FCV:1;
	uint8_t  ACD:1;
	uint8_t  PRM:1;
	uint8_t  DIR:1;
public:
	void initActiveS2M(CONTROL_FUN_ACTIVE fun=CONTROL_FUN_ACTIVE_09_LINK);
	void initPasiveS2M(CONTROL_FUN_PASIVE fun=CONTROL_FUN_PASIVE_00_ACK);
	bool append(class Buffer& b);
};
class Address
{
public:
	uint16_t A1;
	uint16_t A2;
	uint8_t  T0:1;
	uint8_t  A3:7;
public:
	Address(uint16_t a1=0x4301, uint16_t a2=256, uint8_t a3=0);
	void init(uint16_t a1=0x4301, uint16_t a2=256, uint8_t a3=0);
	void init(const string& s="4301", uint16_t a2=256, uint8_t a3=0);
	void region(const string& s="4301");
	bool append(class Buffer& b);
};
class Function
{
public:
	uint8_t AFN;
public:
	void initConfirm	(void);
	void initDeny		(void);
	void initOneByOne	(void);
	void initLogin		(void);
	void initLogout		(void);
	void initHeartbeat	(void);
	void initSetTask	(void);
	void initHistory	(void);
public:
	bool append(class Buffer& b);
};
class Sequence
{
public:
	uint8_t SEQ:4;
	uint8_t CON:1;
	uint8_t POS:2;
	uint8_t TPV:1;
public:
	void initSingleAck(uint8_t seq);
	void initSingleNack(uint8_t seq);
	bool append(class Buffer& b);
};
class Buffer;
class Frame
{
public:
	Header   header;
	Control  control;
	Address  address;
	Function function;
	Sequence sequence;
protected:
	Frame(void);
public:
	void	 clear			(void);
	void	 dataLength		(uint16_t);
	bool	 append			(Buffer&);
	bool	 checkHeader	(void)const;
	int		 checkHeader	(int )const;
	int		 checkFrame		(int );
	uint16_t headerLength	(void)const;
	uint16_t commonLength	(void)const;
	uint16_t dataLength		(void)const;
	uint16_t frameLength	(void)const;
	string	 toString		(void)const;
};
#pragma pack(0)
